package org.nativejpa.parser;

import java.util.Properties;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.net.URL;

/**
 * Mapping <persistence-unit>
 * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
* @create 2009-2-18 22:47:50
*/
public class PersistenceUnit implements Cloneable{
    private URL persistenceXML = null;
    private String unitName;
    private List<String> mappingFiles = new ArrayList<String>(4);

    private Properties props = new Properties();

    public PersistenceUnit(String unitName, URL persistenceXML) {
        this.unitName = unitName;
        this.persistenceXML = persistenceXML;
    }

    public void addMappingFile(String mappingFile) {
        mappingFiles.add(mappingFile);
    }

    public String[] getMappingFiles(){
        return mappingFiles.toArray(new String[mappingFiles.size()]);
    }

    public Properties getAllProperties(){
        return props;
    }

    public void addProperties(Properties props) {
        for(Object key : props.keySet()){
            this.props.setProperty((String)key, props.getProperty((String)key));
        }
    }

    public void addProperty(String key, String value){
        props.setProperty(key, value);
    }

    public String getProperty(String key) {
        return props.getProperty(key);
    }

    public boolean containsKey(String key){
        return props.containsKey(key);
    }

    public String getUnitName() {
        return unitName;
    }

    public URL getPersistenceXML() {
        return persistenceXML;
    }

    public String getJtaDataSourceName() {
        if(containsKey(PersistenceXML.JTA_DATA_SOURCE)) {
            return getProperty(PersistenceXML.JTA_DATA_SOURCE);
        }
        else {
            return null;
        }

    }

    public String getDataSourceJdbcDriver(){
        return getProperty(PersistenceXML.DATASOURCE_JDBC_DRIVER);
    }

    public String getDataSourceJdbcURL(){
        return getProperty(PersistenceXML.DATASOURCE_JDBC_URL);
    }

    public String getDataSourceJdbcUsername(){
        return getProperty(PersistenceXML.DATASOURCE_JDBC_USERNAME);
    }

    public String getDataSourceJdbcPassword(){
        return getProperty(PersistenceXML.DATASOURCE_JDBC_PASSWORD);
    }

    public String getDataSourceXADriver (){
        return getProperty(PersistenceXML.DATASOURCE_XA_DRIVER);
    }

    public boolean isUsingXADataSourceDriver() {
        return props.containsKey(PersistenceXML.DATASOURCE_XA_DRIVER);
    }

    public Properties getXADriverProperties(){
        Properties xaDriverProperties = new Properties();
        Properties allProperties = getAllProperties();
        for( Map.Entry<Object, Object> entry : allProperties.entrySet()){
            String key = entry.getKey().toString();
            if(key.startsWith(PersistenceXML.DATASOURCE_XA_DRIVER_PROPERTY_PREFIX)) {
                xaDriverProperties.put(key.substring(PersistenceXML.DATASOURCE_XA_DRIVER_PROPERTY_PREFIX.length()), entry.getValue().toString());
            }
        }
        return xaDriverProperties;
    }

    public int getDataSourcePoolMinSize(){
        if(containsKey(PersistenceXML.DATASOURCE_POOL_MINSIZE)) {
            return Integer.parseInt(getProperty(PersistenceXML.DATASOURCE_POOL_MINSIZE));
        }
        else {
            return 1;
        }
    }

    public int getDataSourcePoolMaxSize(){
        if(containsKey(PersistenceXML.DATASOURCE_POOL_MAXSIZE)) {
            return Integer.parseInt(getProperty(PersistenceXML.DATASOURCE_POOL_MAXSIZE));
        }
        else {
            return 10;
        }
    }

    public long getDataSourcePoolMaxIdleTime(){
        if(containsKey(PersistenceXML.DATASOURCE_POOL_MAX_IDLE)) {
            return Long.parseLong(getProperty(PersistenceXML.DATASOURCE_POOL_MAX_IDLE));
        }
        else {
            return 10*60; //10m;
        }
    }

    public String getDataSourcePoolTestQuery() {
        if(containsKey(PersistenceXML.DATASOURCE_POOL_TEST_QUERY)) {
            return getProperty(PersistenceXML.DATASOURCE_POOL_TEST_QUERY);
        }
        else {
            return null;
        }
    }

    public int getDataSourcePoolConnectTimeout(){
        if(containsKey(PersistenceXML.DATASOURCE_POOL_CONNECT_TIMEOUT)) {
            return Integer.parseInt(getProperty(PersistenceXML.DATASOURCE_POOL_CONNECT_TIMEOUT));
        }
        else {
            return 30; //30s
        }
    }


    public String getCacheType() {
        if(containsKey(PersistenceXML.CACHE_TYPE)) {
            return getProperty(PersistenceXML.CACHE_TYPE);
        }
        else {
            return PersistenceXML.CACHE_TYPE_DISABLED;
        }
    }

    public int getCacheLocalMaxSize() {
        if(containsKey(PersistenceXML.CACHE_LOCAL_MAXSIZE)) {
            return Integer.parseInt(getProperty(PersistenceXML.CACHE_TYPE));
        }
        else {
            return 0;
        }
    }

    public PersistenceUnit clonePersistenceUnit() {
        PersistenceUnit persistenceUnit = new PersistenceUnit(this.getUnitName(), this.getPersistenceXML());
        persistenceUnit.addProperties(this.getAllProperties());
        return persistenceUnit;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        PersistenceUnit that = (PersistenceUnit) o;

        if (props != null ? !props.equals(that.props) : that.props != null) return false;
        if (unitName != null ? !unitName.equals(that.unitName) : that.unitName != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = unitName != null ? unitName.hashCode() : 0;
        result = 31 * result + (props != null ? props.hashCode() : 0);
        return result;
    }
    

// TODO: default value for connection pool
    // TODO: improve conn pool config
}
